﻿
#region 版权信息
/* ==============================================================================
   * 文 件 名: UpFile
   * 功能描述：文件上传类
   * Copyright (c) 2013 
   * 创 建 人: mashanlin m.sh.lin0328@163.com
   * 修改记录：2013-5-17：重新规范命名  方法重新定义与优化
   * 完成时间: 2012-1-8 15:25:00
   * 修改描述: 通用文件上传类
   * 版    本: v1.0.0.0
   * ==============================================================================*/
#endregion
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Drawing;
using System.Configuration;
using System.Threading;
using System.Net;
using System.Web;
using System.Web.UI.WebControls;
using MSL.Utility.Images;

namespace MSL.Utility.Net
{
    /// <summary>
    /// 文件上传类
    /// </summary>
    public class UpFile
    {
        #region 私有变量

        //以下字段可以配置        
        private String _savePath;                           //保存文件的的完整物理路径(含扩展名) 
        private bool _isDateFolder = true;                      //是否以日期生成文件夹
        private long _size;                                     //允许上传的文件的大小
        private FileMessage _fileMsg;
        private FileMessage[] _fileInfo;
        private String _ype = ".jpg|.gif|.jpeg|.pjpeg|.png|.bmp|.doc|.docx|.ppt|.pptx|.xls|.xlsx|.txt|.pdf|.rar|.zip";// 允许上传的文件类型(默认为图片类型)

        #endregion

        #region 属性
        /// <summary>
        /// 保存文件的文件夹路径(格式为：upload/product/)
        /// </summary>
        public string SavePath
        {
            get { return this._savePath; }
            set { this._savePath = value; }
        }
        /// <summary>
        /// 是否以日期生成文件夹
        /// </summary>
        public bool IsDateFolder
        {
            get { return this._isDateFolder; }
            set { this._isDateFolder = value; }
        }
        /// <summary>
        /// 允许上传的文件类型
        /// </summary>
        public string Type
        {
            get { return this._ype; }
            set { this._ype = value; }
        }
        /// <summary>
        /// 允许上传的文件的大小
        /// </summary>
        public long Size
        {
            get { return this._size; }
            set { this._size = value; }
        }
        /// <summary>
        /// 上传成功文件
        /// </summary>
        public FileMessage Message
        {
            get { return this._fileMsg; }
            set { this._fileMsg = value; }
        }
        /// <summary>
        /// 上传成功文件数组
        /// </summary>
        public FileMessage[] FileInfo
        {
            get { return this._fileInfo; }
            set { this._fileInfo = value; }
        }

        #endregion

        #region 构造函数
        /// <summary>
        /// 
        /// </summary>
        public UpFile()
        {
            this._size = 1024; //上传文件的大小,默认200KB 
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="saveFolder">文件保存路径</param>
        /// <param name="isDateFolder">是否开启日期文件夹存放文件</param>
        /// <param name="fileType">允许上传文件类型(可空)</param>
        /// <param name="sizes">最大允许上传文件的大小(为0时按默认值)</param>
        public UpFile(string saveFolder, bool isDateFolder, string fileType, int sizes)
        {
            this._savePath = saveFolder;
            this.IsDateFolder = isDateFolder;
            if (fileType == "")
            {
                this._ype = "jpg|gif|bmp|jpeg|png|rar|doc";
            }
            else
            {
                this._ype = fileType;
            }
            if (sizes == 0)
            {
                this._size = 1024;//上传文件的大小,默认200KB 
            }
            else
            {
                this._size = sizes;
            }
        }
        #endregion

        #region 批量上传文件
        /// <summary>
        /// 保存上传文件(任意类型文件)
        /// </summary>
        /// <param name="files">input file控件数组</param>
        /// <returns>文件路径，多路径间用|隔开</returns>
        public string UploadFile(HttpFileCollection files)
        {
            string myReturn = string.Empty;
            string saveFileName = string.Empty;
            string savePath = string.Empty;
            try
            {
                this._fileInfo = new FileMessage[files.Count];
                //保存文件夹路径 
                this._savePath = GetSaveFilePath();
                for (int i = 0; i < files.Count; i++)
                {
                    //上传路径 
                    if (String.IsNullOrEmpty(this._savePath))
                    {
                        continue;
                    }
                    else
                    {
                        long size = files[i].ContentLength;
                        if (size >= this._size * 1024)
                        {
                            throw new Exception("上传的文件不能大于" + this._size + "KB");
                        }
                        //获得原文件名（含扩展名） 
                        string origiFile = System.IO.Path.GetFileName(files[i].FileName);
                        //以日期命名
                        saveFileName = DateTime.UtcNow.ToString("yyyy" + "MM" + "dd" + "HH" + "mm" + "ss" + "ffffff");
                        //原文件扩展名 
                        string prefix = GetFileExt(origiFile);
                        if (prefix == "")
                        {
                            throw new Exception("您只能上传扩展名为:" + this._ype + "的文件");
                        }
                        //保存文件物理路径 
                        savePath = this._savePath + saveFileName + prefix;
                        //保存文件
                        files[i].SaveAs(this._savePath);

                        this._fileInfo[i].FileName = files[i].FileName;
                        this._fileInfo[i].Size = size;
                        this._fileInfo[i].FileType = prefix;
                        this._fileInfo[i].SavePath = savePath;
                        this._fileInfo[i].Path = this._savePath;
                        myReturn = myReturn + ((String.IsNullOrEmpty(myReturn)) ? "" : "|") + savePath.TrimStart(new char[] { '|' }) + this._savePath + prefix;
                    }
                }
            }
            catch
            {
                throw new Exception("出现未知错误");
            }
            return myReturn;
        }

        #endregion

        #region 上传单文件

        /// <summary>
        /// 上传文件（默认文件名）
        /// </summary>
        /// <param name="fu">上传控件ID</param>
        /// <param name="IsTimeName">启用时间重命名</param>
        /// <returns></returns>
        public string UploadFile(FileUpload fu, bool IsTimeName)
        {
            string saveFileName = fu.FileName;
            string savePath = string.Empty;
            try
            {
                this._fileMsg = new FileMessage();
                this._savePath = GetSaveFilePath();
                if (IsTimeName)//以日期命名
                {
                    saveFileName = DateTime.UtcNow.ToString("yyyy" + "MM" + "dd" + "HH" + "mm" + "ss" + "ffffff");
                }
                else
                {
                    saveFileName = Guid.NewGuid().ToString();
                }
                string origiFile = System.IO.Path.GetFileName(fu.FileName);
                string prefix = GetFileExt(origiFile);
                long size = fu.FileContent.Length;
                if (size >= this._size * 1024)
                {
                    throw new Exception("上传的文件不能大于" + this._size + "KB");
                }
                if (prefix == "")
                {
                    throw new Exception("您只能上传扩展名为:" + this._ype + "的文件");
                }
                //保存文件的物理路径 
                savePath = this._savePath + saveFileName + prefix;
                fu.SaveAs(savePath);

                this._fileMsg.FileName = fu.FileName;
                this._fileMsg.Size = size;
                this._fileMsg.FileType = prefix;
                this._fileMsg.SavePath = savePath;
                this._fileMsg.Path = this._savePath;
            }
            catch
            {
                throw new Exception("出现未知错误！");
            }
            return savePath;
        }

        /// <summary>
        /// 上传文件（默认文件名）
        /// </summary>
        /// <param name="fu">上传控件ID</param>
        /// <param name="IsTimeName">启用时间重命名</param>
        /// <returns></returns>
        public string UploadFile(HttpPostedFile fu, bool IsTimeName)
        {
            string saveFileName = fu.FileName;
            string savePath = string.Empty;
            try
            {
                this._fileMsg = new FileMessage();
                this._savePath = GetSaveFilePath();
                if (IsTimeName)
                {
                    saveFileName = DateTime.UtcNow.ToString("yyyy" + "MM" + "dd" + "HH" + "mm" + "ss" + "ffffff");
                }
                else
                {
                    saveFileName = Guid.NewGuid().ToString();
                }
                string origiFile = System.IO.Path.GetFileName(saveFileName);
                string prefix = GetFileExt(origiFile);
                long size = fu.ContentLength;
                if (size >= this._size * 1024)
                {
                    throw new Exception("上传的文件不能大于" + this._size + "KB");
                }
                if (prefix == "")
                {
                    throw new Exception("您只能上传扩展名为:" + this._ype + "的文件");
                }
                //文件的物理路径 
                savePath = this._savePath + saveFileName + prefix;
                fu.SaveAs(this._savePath);

                this._fileMsg.FileName = fu.FileName;
                this._fileMsg.Size = size;
                this._fileMsg.FileType = prefix;
                this._fileMsg.SavePath = savePath;
                this._fileMsg.Path = this._savePath;
            }
            catch
            {
                throw new Exception("出现未知错误！");
            }
            return savePath;
        }
        #endregion

        #region 上传图片

        /// <summary>
        /// 上传图片并压缩图片大小
        /// 四各形式：1)指定高 按比例缩放; 2)指定宽 按比例缩放; 3)不缩放; 4)指定宽高裁剪(不会变形).
        /// </summary>
        /// <param name="fu">FileUpload对象</param>
        /// <param name="width">指定宽度</param>
        /// <param name="height">指定高度</param>
        /// <param name="markThumb">是否生成缩略图</param>
        /// <returns>返回文件存储的完整路径</returns>
        public string UploadPicture(System.Web.UI.WebControls.FileUpload fu, int width, int height, bool markThumb)
        {
            if (!fu.HasFile)
            {
                return null;
            }
            string prefix = System.IO.Path.GetExtension(fu.FileName);
            string savePath = string.Empty;
            this._fileMsg = new FileMessage();
            if (AllowPictureUp(prefix))
            {
                string strFileName = DateTime.Now.ToString("yyyyMMddHHmmssffff") + new Random().Next(1000) + prefix; ;
                //if (IsDateName)
                //{
                //    strFileName = Guid.NewGuid().ToString() + prefix;
                //}
                //保存文件夹路径 
                this._savePath = GetSaveFilePath();
                savePath = this._savePath + strFileName;
                try
                {
                    //获取上传图片的大小
                    Stream PicStream = fu.PostedFile.InputStream;
                    if (width == 0 && height != 0)//指定高 按比例缩放
                    {
                        ImageHelper.MakeThumbnail(PicStream, this._savePath + strFileName, width, height, Zoom.H, prefix);
                    }
                    else if (width != 0 && height == 0)//指定宽 按比例缩放
                    {
                        ImageHelper.MakeThumbnail(PicStream, this._savePath + strFileName, width, height, Zoom.W, prefix);
                    }
                    else if (width == 0 && height == 0)//上传原图
                    {
                        fu.SaveAs(this._savePath + strFileName);
                    }
                    else//指定宽高裁剪(不会变形)
                    {
                        ImageHelper.MakeThumbnail(PicStream, this._savePath + strFileName, width, height, Zoom.Cut, prefix);
                    }
                    if (markThumb)//生成缩略图
                    {
                        ImageHelper.MakeThumbnail(PicStream, this._savePath + "small\\" + strFileName, 300, 375, Zoom.W, prefix);
                    }
                    this._fileMsg.FileName = strFileName;
                    this._fileMsg.Size = fu.FileContent.Length;
                    this._fileMsg.FileType = prefix;
                    this._fileMsg.SavePath = savePath;
                    this._fileMsg.Path = this._savePath;
                    return savePath;
                }
                catch
                {
                    return null;
                }
            }
            else
            {
                return null;
            }
        }
        /// <summary>
        /// 保存上传文件(图片文件)
        /// </summary>
        /// <param name="files">input file控件数组</param>
        /// <param name="maxWidth">最大宽度</param>
        /// <returns>图片文件路径，多路径间用|隔开</returns>
        public string UploadPicture(HttpFileCollection files, int maxWidth)
        {
            string myReturn = string.Empty;
            string saveFileName = string.Empty;
            string savePath = string.Empty;
            try
            {
                //上传路径 
                if (String.IsNullOrEmpty(this._savePath))
                {
                    return null;
                }
                //保存文件夹路径 
                this._savePath = GetSaveFilePath();
                this._fileInfo = new FileMessage[files.Count];
                for (int i = 0; i < files.Count; i++)
                {

                    long size = files[i].ContentLength;
                    if (size >= this._size * 1024)
                    {
                        throw new Exception("上传的文件不能大于" + this._size + "KB");
                    }
                    //获得原文件名（含扩展名） 
                    string origiFile = System.IO.Path.GetFileName(files[i].FileName);
                    string prefix = System.IO.Path.GetExtension(files[i].FileName);
                    saveFileName = DateTime.Now.ToString("yyyyMMddHHmmssffff") + new Random().Next(1000) + prefix; ;

                    if (!AllowPictureUp(prefix))
                    {
                        throw new Exception("您只能上传扩展名为:.jpg|.gif|.jpeg|.pjpeg|.png的文件");
                    }
                    //得到保存文件物理路径 
                    savePath = this._savePath + saveFileName + prefix;

                    #region 保存文件并生成缩略图

                    Bitmap img = new Bitmap(files[i].InputStream);
                    Stream picStream = files[i].InputStream;
                    int imgw = img.Width, imgh = img.Height;
                    int imgSize = files[i].ContentLength;//图像文件占用空间大小 
                    if (maxWidth == 0)
                    {
                        maxWidth = 500;
                    }
                    //保存文件
                    if (imgw > maxWidth)//如果图片宽大于maxWidth像素，则生成缩略图
                    {
                        ImageHelper.MakeThumbnail(picStream, this._savePath, maxWidth, 0, Zoom.W, "Cut");
                    }
                    else if (size > 500)//如果图片大小大于500(kb)时自动按原尺寸压缩
                    {
                        ImageHelper.MakeThumbnail(picStream, this._savePath, imgw, 0, Zoom.W, prefix.Substring(1));
                    }
                    else
                    {
                        files[i].SaveAs(this._savePath);
                    }

                    this._fileInfo[i].FileName = files[i].FileName;
                    this._fileInfo[i].Size = size;
                    this._fileInfo[i].FileType = prefix;
                    this._fileInfo[i].SavePath = savePath;
                    this._fileInfo[i].Path = this._savePath;
                    #endregion

                    myReturn = myReturn + ((String.IsNullOrEmpty(myReturn)) ? "" : "|") + savePath.TrimStart(new char[] { '|' }) + this._savePath + prefix;
                }
            }
            catch
            {
                throw new Exception("出现未知错误！");
            }
            return myReturn;
        }
        /// <summary>
        /// 上传图片
        /// </summary>
        /// <param name="fu">input file控件</param>
        /// <param name="maxWidth"></param>
        /// <returns>图片文件路径</returns>
        public string UploadPicture(HttpPostedFile fu, int maxWidth)
        {
            string saveFileName = fu.FileName;
            string savePath = string.Empty;
            try
            {
                this._fileMsg = new FileMessage();
                this._savePath = GetSaveFilePath();
                this._savePath = GetSaveFilePath();//保存文件夹路径 

                Random rd = new Random();
                string origiFile = System.IO.Path.GetFileName(saveFileName);
                string prefix = GetFileExt(origiFile);
                long size = fu.ContentLength;
                if (size >= this._size * 1024)
                {
                    throw new Exception("上传的文件不能大于" + this._size + "KB");
                }
                saveFileName = DateTime.Now.ToString("yyyyMMddHHmmssffff") + new Random().Next(1000) + prefix;
                if (!AllowPictureUp(prefix))
                {
                    throw new Exception("您只能上传扩展名为:.jpg|.gif|.jpeg|.pjpeg|.png的文件");
                }
                savePath = this._savePath + saveFileName + prefix; //得到保存文件物理路径 

                #region 保存文件并生成缩略图

                Bitmap img = new Bitmap(fu.InputStream);
                Stream picStream = fu.InputStream;
                int imgw = img.Width, imgh = img.Height;
                if (maxWidth == 0)
                {
                    maxWidth = 500;
                }
                //保存文件
                if (imgw > maxWidth)//如果图片宽大于maxWidth像素，则生成缩略图
                {
                    ImageHelper.MakeThumbnail(picStream, this._savePath, maxWidth, 0, Zoom.W, "Cut");
                }
                else if (size > 500 * 1024)//如果图片大小大于500(kb)时自动按原尺寸压缩
                {
                    ImageHelper.MakeThumbnail(picStream, this._savePath, imgw, 0, Zoom.W, prefix.Substring(1));
                }
                else
                {
                    fu.SaveAs(this._savePath);
                }
                #endregion
            }
            catch
            {
                throw new Exception("出现未知错误！");
            }
            return savePath;
        }
        #endregion

        #region 私有方法

        #region 获得保存的文件夹的路径
        /// <summary> 
        /// 获得保存的文件夹的物理路径 
        /// </summary> 
        /// <returns>保存的文件夹的物理路径,若为null则表示出错</returns> 
        private String GetSaveFilePath()
        {
            string path = string.Empty;

            try
            {
                if (this._isDateFolder)
                {
                    if (!this._savePath.EndsWith("\\"))
                    {
                        path = this._savePath + "\\" + DateTime.Now.ToString("yyyy-MM-dd").Replace("-", "\\");
                    }
                    else
                    {
                        path = this._savePath + DateTime.Now.ToString("yyyy-MM-dd").Replace("-", "\\");
                    }
                    path = CreateMatchFolder(path);
                }
                else
                {
                    path = CreateMatchFolder(this._savePath);
                }

            }
            catch
            {
                MessageBox("获取保存路径出错");
            }
            return path;
        }
        #endregion

        #region 获取文件的扩展名
        /// <summary> 
        /// 获取文件的扩展名
        /// </summary> 
        /// <param name="myFileName">原文件名(带后缀)</param> 
        /// <returns>原扩展名;若为null,表明文件无后缀名;若返回为"",则表明扩展名为非法.</returns> 
        private String GetFileExt(string myFileName)
        {
            //获得文件扩展名 
            string myFileExt = System.IO.Path.GetExtension(myFileName);
            if (myFileExt.Equals(string.Empty))
            {
                return null;
            }
            bool flag = false;
            //是否允许上传 
            foreach (string ext in this._ype.Split('|'))
            {
                if (String.Equals(ext, myFileExt, StringComparison.CurrentCultureIgnoreCase))
                {
                    flag = true;
                    break;
                }
            }
            if (!flag)
            {
                myFileExt = "";
            }
            return myFileExt;
        }

        #endregion

        #region 弹出消息框
        /// <summary> 
        /// 弹出消息框并跳转到指定页面 
        /// </summary> 
        /// <param name="msg">显示内容</param> 
        /// <param name="url">跳转路径</param> 
        private void MessageBox(string msg, string url)
        {
            HttpContext.Current.Response.Write("<script language=javascript>alert('" + msg + "');window.location='" + url + "'</script>");
        }
        /// <summary> 
        /// 弹出消息框无跳转
        /// </summary> 
        /// <param name="msg">显示内容</param> 
        private void MessageBox(string msg)
        {
            HttpContext.Current.Response.Write("<script language=javascript>alert('" + msg + "');</script>");
        }
        #endregion
        /// <summary>
        /// 创建文件夹(不存在就创建)
        /// </summary>
        /// <param name="path">文件夹物理路径</param>
        private String CreateMatchFolder(string path)
        {
            if (path.EndsWith("\\"))
            {
                path = path.Remove(path.LastIndexOf("\\"));
            }
            if (!Directory.Exists(path))
            {
                Directory.CreateDirectory(path);
            }
            return path + "\\";
        }
        /// <summary>
        /// 是否允许上传图片
        /// </summary>
        /// <param name="prefix">后缀</param>
        /// <returns></returns>
        private bool AllowPictureUp(string prefix)
        {
            bool isUp = false;//是允许上传
            string[] allowExtensions = new string[] { ".jpg", ".jpeg", ".bmp", ".gif", ".pjpeg", ".png" };
            for (int i = 0; i < allowExtensions.Length; i++)
            {
                //找到对应后缀
                if (prefix == allowExtensions[i])
                {
                    isUp = true;
                    break;
                }
            }
            return isUp;
        }
        #endregion
    }
    /// <summary>
    /// 文件实体
    /// </summary>
    public class FileMessage
    {
        /// <summary>
        /// 文件大小
        /// </summary>
        public long Size { get; set; }
        /// <summary>
        /// 文件上传路径
        /// </summary>
        public string Path { get; set; }
        /// <summary>
        /// 文件保存路径
        /// </summary>
        public string SavePath { get; set; }
        /// <summary>
        /// 文件类型
        /// </summary>
        public string FileType { get; set; }
        /// <summary>
        /// 文件名
        /// </summary>
        public string FileName { get; set; }
    }
}
